fdo#70838: apply rotation transformations to DML anchor position
Used the same algorithm that we had for VML to update the position of
the DML anchor taking into account the rotation of the shape.
Complemented the unit test to check the values in the generated DML.
Change-Id: Ie0293c3cf4d1309fad58c0387f1589e69071fd9a
diff --git a/sw/qa/extras/ooxmlexport/ooxmlsdrexport.cxx b/sw/qa/extras/ooxmlexport/ooxmlsdrexport.cxx
index 918af37..c8f45e3 100644
--- a/sw/qa/extras/ooxmlexport/ooxmlsdrexport.cxx
+++ b/sw/qa/extras/ooxmlexport/ooxmlsdrexport.cxx
@@ -490,6 +490,54 @@
if (!pXmlDocument)
return;
// Check DML document
sal_Int32 aXPos[4], aYPos[4];
aXPos[0] = getXPathContent(pXmlDocument, "/w:document/w:body/w:p/w:r/mc:AlternateContent[1]/mc:Choice/w:drawing/wp:anchor/wp:positionH/wp:posOffset").toInt32();
aXPos[1] = getXPathContent(pXmlDocument, "/w:document/w:body/w:p/w:r/mc:AlternateContent[2]/mc:Choice/w:drawing/wp:anchor/wp:positionH/wp:posOffset").toInt32();
aXPos[2] = getXPathContent(pXmlDocument, "/w:document/w:body/w:p/w:r/mc:AlternateContent[3]/mc:Choice/w:drawing/wp:anchor/wp:positionH/wp:posOffset").toInt32();
aXPos[3] = getXPathContent(pXmlDocument, "/w:document/w:body/w:p/w:r/mc:AlternateContent[4]/mc:Choice/w:drawing/wp:anchor/wp:positionH/wp:posOffset").toInt32();
aYPos[0] = getXPathContent(pXmlDocument, "/w:document/w:body/w:p/w:r/mc:AlternateContent[1]/mc:Choice/w:drawing/wp:anchor/wp:positionV/wp:posOffset").toInt32();
aYPos[1] = getXPathContent(pXmlDocument, "/w:document/w:body/w:p/w:r/mc:AlternateContent[2]/mc:Choice/w:drawing/wp:anchor/wp:positionV/wp:posOffset").toInt32();
aYPos[2] = getXPathContent(pXmlDocument, "/w:document/w:body/w:p/w:r/mc:AlternateContent[3]/mc:Choice/w:drawing/wp:anchor/wp:positionV/wp:posOffset").toInt32();
aYPos[3] = getXPathContent(pXmlDocument, "/w:document/w:body/w:p/w:r/mc:AlternateContent[4]/mc:Choice/w:drawing/wp:anchor/wp:positionV/wp:posOffset").toInt32();
// TODO: compare values with a reference value extracted from the original document
// depends on fdo#75722
// certain degree of error is tolerated due to rounding in unit conversions
CPPUNIT_ASSERT(abs(aXPos[0] - aXPos[1]) < 1000);
CPPUNIT_ASSERT(abs(aXPos[1] - aXPos[2]) < 1000);
CPPUNIT_ASSERT(abs(aXPos[2] - aXPos[3]) < 1000);
CPPUNIT_ASSERT(abs(aYPos[0] - aYPos[1]) < 1000);
CPPUNIT_ASSERT(abs(aYPos[1] - aYPos[2]) < 1000);
CPPUNIT_ASSERT(abs(aYPos[2] - aYPos[3]) < 1000);
sal_Int32 aHSize[4], aVSize[4];
aHSize[0] = getXPath(pXmlDocument, "/w:document/w:body/w:p/w:r/mc:AlternateContent[1]/mc:Choice/w:drawing/wp:anchor/wp:extent", "cx").toInt32();
aHSize[1] = getXPath(pXmlDocument, "/w:document/w:body/w:p/w:r/mc:AlternateContent[2]/mc:Choice/w:drawing/wp:anchor/wp:extent", "cx").toInt32();
aHSize[2] = getXPath(pXmlDocument, "/w:document/w:body/w:p/w:r/mc:AlternateContent[3]/mc:Choice/w:drawing/wp:anchor/wp:extent", "cx").toInt32();
aHSize[3] = getXPath(pXmlDocument, "/w:document/w:body/w:p/w:r/mc:AlternateContent[4]/mc:Choice/w:drawing/wp:anchor/wp:extent", "cx").toInt32();
aVSize[0] = getXPath(pXmlDocument, "/w:document/w:body/w:p/w:r/mc:AlternateContent[1]/mc:Choice/w:drawing/wp:anchor/wp:extent", "cy").toInt32();
aVSize[1] = getXPath(pXmlDocument, "/w:document/w:body/w:p/w:r/mc:AlternateContent[2]/mc:Choice/w:drawing/wp:anchor/wp:extent", "cy").toInt32();
aVSize[2] = getXPath(pXmlDocument, "/w:document/w:body/w:p/w:r/mc:AlternateContent[3]/mc:Choice/w:drawing/wp:anchor/wp:extent", "cy").toInt32();
aVSize[3] = getXPath(pXmlDocument, "/w:document/w:body/w:p/w:r/mc:AlternateContent[4]/mc:Choice/w:drawing/wp:anchor/wp:extent", "cy").toInt32();
// certain degree of error is tolerated due to rounding in unit conversions
CPPUNIT_ASSERT(abs(3599280 - aHSize[0]) < 1000);
CPPUNIT_ASSERT(abs(3599280 - aHSize[1]) < 1000);
CPPUNIT_ASSERT(abs(3599280 - aHSize[2]) < 1000);
CPPUNIT_ASSERT(abs(3599280 - aHSize[3]) < 1000);
CPPUNIT_ASSERT(abs(1799640 - aVSize[0]) < 1000);
CPPUNIT_ASSERT(abs(1799640 - aVSize[1]) < 1000);
CPPUNIT_ASSERT(abs(1799640 - aVSize[2]) < 1000);
CPPUNIT_ASSERT(abs(1799640 - aVSize[3]) < 1000);
// Check VML document
// get styles of the four shapes
OUString aStyles[4];
aStyles[0] = getXPath( pXmlDocument, "/w:document/w:body/w:p/w:r/mc:AlternateContent[1]/mc:Fallback/w:pict/v:rect", "style");
diff --git a/sw/source/filter/ww8/docxsdrexport.cxx b/sw/source/filter/ww8/docxsdrexport.cxx
index 4d755fc..8add83f 100644
--- a/sw/source/filter/ww8/docxsdrexport.cxx
+++ b/sw/source/filter/ww8/docxsdrexport.cxx
@@ -86,6 +86,35 @@
return aResult;
}
void lclMovePositionWithRotation(awt::Point& aPos, sal_Int64 nRotation)
{
// code from ImplEESdrWriter::ImplFlipBoundingBox (filter/source/msfilter/eschesdo.cxx)
// TODO: refactor
if ( nRotation == 0 )
return;
if ( nRotation < 0 )
nRotation = ( 36000 + nRotation ) % 36000;
if ( nRotation % 18000 == 0 )
nRotation = 0;
while ( nRotation > 9000 )
nRotation = ( 18000 - ( nRotation % 18000 ) );
double fVal = (double) nRotation * F_PI18000;
double fCos = cos( fVal );
double fSin = sin( fVal );
double nWidthHalf = (double) aPos.X / 2;
double nHeightHalf = (double) aPos.Y / 2;
double nXDiff = fSin * nHeightHalf + fCos * nWidthHalf - nWidthHalf;
double nYDiff = fSin * nWidthHalf + fCos * nHeightHalf - nHeightHalf;
aPos.X += nXDiff;
aPos.Y += nYDiff;
}
}
ExportDataSaveRestore::ExportDataSaveRestore(DocxExport& rExport, sal_uLong nStt, sal_uLong nEnd, sw::Frame* pParentFrame)
@@ -268,11 +297,14 @@
{
sax_fastparser::FastAttributeList* attrList = m_pImpl->m_pSerializer->createAttrList();
bool bOpaque = pFrmFmt->GetOpaque().GetValue();
awt::Point aPos(pFrmFmt->GetHoriOrient().GetPos(), pFrmFmt->GetVertOrient().GetPos());
const SdrObject* pObj = pFrmFmt->FindRealSdrObject();
if (pObj != NULL)
{
// SdrObjects know their layer, consider that instead of the frame format.
bOpaque = pObj->GetLayer() != pFrmFmt->GetDoc()->GetHellId() && pObj->GetLayer() != pFrmFmt->GetDoc()->GetInvisibleHellId();
lclMovePositionWithRotation(aPos, pObj->GetRotateAngle());
}
attrList->add(XML_behindDoc, bOpaque ? "0" : "1");
attrList->add(XML_distT, OString::number(TwipsToEMU(pULSpaceItem.GetUpper())).getStr());
@@ -394,7 +426,7 @@
else
{
m_pImpl->m_pSerializer->startElementNS(XML_wp, XML_posOffset, FSEND);
m_pImpl->m_pSerializer->write(TwipsToEMU(pFrmFmt->GetHoriOrient().GetPos()));
m_pImpl->m_pSerializer->write(TwipsToEMU(aPos.X));
m_pImpl->m_pSerializer->endElementNS(XML_wp, XML_posOffset);
}
m_pImpl->m_pSerializer->endElementNS(XML_wp, XML_positionH);
@@ -408,7 +440,7 @@
else
{
m_pImpl->m_pSerializer->startElementNS(XML_wp, XML_posOffset, FSEND);
m_pImpl->m_pSerializer->write(TwipsToEMU(pFrmFmt->GetVertOrient().GetPos()));
m_pImpl->m_pSerializer->write(TwipsToEMU(aPos.Y));
m_pImpl->m_pSerializer->endElementNS(XML_wp, XML_posOffset);
}
m_pImpl->m_pSerializer->endElementNS(XML_wp, XML_positionV);